'use strict';

const cp = require('child_process');
const path = require('path');
const Package = require('@jay-cli-dev/package');
const log = require('@jay-cli-dev/log');

// 命令和命令包的映射
const SETTINGS = {
    init: '@imooc-cli/init'
}

// 缓存目录
const CACHE_DIR = 'dependencies';

async function exec() {
    // 获取环境变量的值
    let targetPath = process.env.CLI_TARGET_PATH;
    const homePath = process.env.CLI_HOME_PATH;

    let storeDir = '';
    let pkg;

    // 打印调试信息
    log.verbose('targetPath', targetPath);
    log.verbose('homePath', homePath);

    const cmdObj = arguments[arguments.length - 1];
    const cmdName = cmdObj.name();
    const packageName = SETTINGS[cmdName];
    const packageVersion = 'latest'; // 默认使用最新的包

    if (!targetPath) {
        targetPath = path.resolve(homePath, CACHE_DIR); // 缓存路径
        storeDir = path.resolve(targetPath, 'node_modules'); // 缓存依赖包路径
        log.verbose('targetPath', targetPath);
        log.verbose('storeDir', storeDir);
        
        // 创建pkg
        pkg = new Package({
            targetPath,
            storeDir,
            packageName,
            packageVersion
        });

        if (await pkg.exists()) { // 若pkg已存在，则更新到最新版
            await pkg.update();
        } else { // 若pkg已存在，则安装最新版
            await pkg.install();
        }

    } else { // 如果当前指定了要执行的命令的包路径，则直接传入
        pkg = new Package({
            targetPath,
            packageName,
            packageVersion
        });
    }

    const rootFile = pkg.getRootFilePath();
    if (rootFile) {
        try {
            // 在当前进程中调用
            // require(rootFile).call(null, Array.from(arguments));

            // 在node子进程中调用
            // 参数精简
            const args = Array.from(arguments);
            const cmd = args[args.length - 1];
            const o = Object.create(null);
            Object.keys(cmd).forEach(key => {
                if (cmd.hasOwnProperty(key) && !key.startsWith('_') && key !== 'parent') {
                    o[key] = cmd[key];
                }
            })
            args[args.length - 1] = o;

            // 使用node子进程调用
            const code = `require('${rootFile}').call(null,${JSON.stringify(args)})`;
            const child = spawn('node', ['-e', code], {
                cwd: process.cwd(),
                stdio: 'inherit'
            });
            child.on('error', e => {
                log.error(e.message);
                process.exit(1);
            });
            child.on('exit', e => {
                log.verbose('命令执行成功:' + e);
                process.exit(0);
            })

        } catch (e) {
            log.error(e.message);    
        }
        
    }
}

function spawn(command, args, options) {
    const win32 = process.platform === 'win32';

    const cmd = win32 ? 'cmd' : command;
    const cmdArgs = win32 ? ['/c'].concat(command, args) : args;

    return cp.spawn(cmd, cmdArgs, options || {});
}
module.exports = exec;
